﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Diagnostics;
using System.Linq;
using System.Text;

using Tradex.ComponentModel;

namespace Tradex.Operations {
    
    /// <summary>
    /// A LogEnty is an entry in the Tradex internal logging system. it is a little more sophisticated
    /// than the windows logging system as it has more references to the origin and cause of the entry.
    /// </summary>
    public sealed class LogEntry {

        /// <summary>
        /// Public Constructor taking all values except the Timestamp.
        /// </summary>
        /// <param name="traceLevel"></param>
        /// <param name="subject"></param>
        /// <param name="message"></param>
        /// <param name="origin"></param>
        /// <param name="reference"></param>
        /// <param name="messageParameters"></param>
        public LogEntry(    
            TraceLevel traceLevel,
            string subject,
            string origin, string reference,
            string message, params object[] messageParameters
        ) {
            Timestamp = DateTime.UtcNow;
            TraceLevel = traceLevel;
            Subject = subject;
            Origin = origin;
            Reference = reference;

            Message = String.Format(CultureInfo.InvariantCulture, message, messageParameters);
        }

        /// <summary>
        /// Public Constructor taking all values.
        /// </summary>
        /// <param name="timestamp"></param>
        /// <param name="traceLevel"></param>
        /// <param name="subject"></param>
        /// <param name="message"></param>
        /// <param name="origin"></param>
        /// <param name="reference"></param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed")]
        public LogEntry(
            DateTime timestamp, TraceLevel traceLevel,
            string subject, string message,
            string origin, string reference = null
        ) {
            Timestamp = timestamp;
            TraceLevel = traceLevel;
            Subject = subject;
            Message = message;
            Origin = origin;
            Reference = reference;
        }

        /// <summary>
        /// This is the timestamp of the log entry. When submitting an entry it may be null, in which case
        /// it will be set at the control service (indicating the time the control service got the message).
        /// This normally will lead to another message, though, and should be seen as bad behavior.
        /// </summary>
        public DateTime Timestamp { get; private set; }

        /// <summary>
        /// This is the trace level of the log entry. They conform to the System.Diagnostics TraceLevel.
        /// </summary>
        public TraceLevel TraceLevel { get; private set; }

        /// <summary>
        /// This is a short string description of the log entry. This can be "Order Modification Failed", for example,
        /// with the Message then containing detailed error information.
        /// </summary>
        public string Subject { get; private set; }

        /// <summary>
        /// This is the detailed message for the log entry. It will be more detailed than the subject. For example an error
        /// generated for an exception will show the full exception output here.
        /// </summary>
        public string Message { get; private set; }

        /// <summary>
        /// This string indicates the origin of the message - this is the particular subsystem, connector or strategy that
        /// causes the log entry to be written. As example, log events originating in the operations service will have
        /// "Services/OperationsSerivice" in here.
        /// </summary>
        public string Origin { get; private set; }

        /// <summary>
        /// This string indicates a reference to the reason of the message. This can be the order that gets entered or blows,
        /// or the strategy that is started. For example, when an order is rejected, the order code will be the reference.
        /// </summary>
        public string Reference { get; private set; }

        /// <inheritdoc />
        public override string ToString() {
            return String.Format(
                CultureInfo.InvariantCulture,
                "{0} {1} {2} {3} {4}",
                Timestamp, TraceLevel, Origin, Subject, Reference
            );
        }

    }

}
